package com.ruoyi.common.core.service;

import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.core.domain.dto.CycleConfig;
import com.ruoyi.common.core.domain.dto.EventPlan;
import com.ruoyi.common.enums.UserDrugType;
import com.ruoyi.common.enums.UserEventType;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.IntStream;

/**
 * Description:
 * Author: YangShiWei
 * Email: strongwalter2014@gmail.com
 * Datetime: 2023/4/16 16:28
 */
public interface UserEventCycleService {

    /**
     * 填充实际的事件信息
     *
     * @param userId
     * @param eventPlanList
     */
    void renderEventInfo(Long userId, List<EventPlan> eventPlanList);

    /**
     * 根据获取的周期信息，填充实际发生的事件信息
     *
     * @param userId
     */
    default List<EventPlan> generatePlansWithEventInfo(Long userId, UserEventType userEventType, UserDrugType userDrugType, Date jdrq) {
        List<EventPlan> plans = generatePlans(userEventType, userDrugType, jdrq, true);
        renderEventInfo(userId, plans);
        return plans;
    }

    /**
     * 根据决定日期生成人员事件周期
     * 涉及人员类型：社戒、社康、社会面有吸毒史、戒断三年未复吸
     * 谈话
     * 社区戒毒、社区康复、社会面：
     * 三年内，每个月一次
     * 戒断三年未复吸：
     * 三个月谈话一次
     *
     * @param userDrugType        人员类型
     * @param jdrq                决定日期
     * @param filterPlansAfterNow 是否过滤掉今天之后的周期数据
     * @return
     */
    default List<EventPlan> generatePlans(UserEventType userEventType, UserDrugType userDrugType, Date jdrq, boolean filterPlansAfterNow) {
        if (jdrq == null || userDrugType == null) return new ArrayList<>();
        if (!userDrugType.getCycleConfigMap().containsKey(userEventType)) return new ArrayList<>();
        List<EventPlan> result = new ArrayList<>();
        AtomicReference<Date> lastDate = new AtomicReference<>(jdrq);
        Date now = new Date();
        CycleConfig cycleConfig = userDrugType.getCycleConfigMap().get(userEventType);
        int termTotal = cycleConfig.getCycleTotal();
        AtomicInteger yearCount = new AtomicInteger(1);
        AtomicInteger monthCount = new AtomicInteger();
        IntStream.range(0, termTotal).forEach(d -> {
            int stepOfThisYear = cycleConfig.getCycleOfYear(yearCount.get());
            Date start = DateUtil.offsetMonth(lastDate.get(), d * stepOfThisYear);
            Date end = DateUtil.offsetMonth(lastDate.get(), (d + 1) * stepOfThisYear);
            monthCount.addAndGet(stepOfThisYear);
            yearCount.set(monthCount.get() / 12 + 1);
            if (!filterPlansAfterNow || (start.before(now) && end.before(now))) {
                result.add(new EventPlan(start, end, userEventType));
            }
        });
        return result;
    }


}
